#ifndef GLWIDGET_H
#define GLWIDGET_H


#include "OpenGL/Angel.h"
#include "OpenGL/obj3d.h"


#include <OgreCamera.h>
#include <OgreEntity.h>
#include <OgreLogManager.h>
#include <OgreRoot.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>
#include <OgreConfigFile.h>

#include <OISEvents.h>
#include <OISInputManager.h>
#include <OISKeyboard.h>
#include <OISMouse.h>

#include <SdkTrays.h>
#include <SdkCameraMan.h>

// Physics module
#include "Bullet/physics.h"

#include <vector>
#include <time.h>
#include <QGLWidget>

#include <QTimer>
#include <QMouseEvent>

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include "Resource.h"
#endif

#define objN 6// # of object


class GLWidget : public QGLWidget
{
    Q_OBJECT

		

private:
    QTimer timer;
public:
    explicit GLWidget(QWidget *parent = 0);

    static const int COMMAND_AIRPLANE  = 0;
    static const int COMMAND_CAMERA  = 1;
    static const int COMMAND_AIRPLANE_MOVE  = 11;
    static const int COMMAND_FLYING  = 100;

    static const int MODE_HORIZONTAL = 0;
    static const int MODE_VERTICAL = 1;
    int controllerMode;

    Obj3D airplane;
    Obj3D missile;
    Obj3D goal;
    vec4 at;
    vec4 up;

    mat4 g_ProjectionMat;
    mat4 g_ViewMat;

    vec4 g_ObjectDefaultColor;
    vec4 g_ObjectSelectionColor;
    vec4 g_ObjectCollisionColor;
    vec4 g_ObjectBoundColor;


    vec4 g_LightAmbient;
    vec4 g_LightDiffuse;
    vec4 g_LightSpecular;
    vec4 g_LightPos;

    bool g_BVVisibleFlag;

    static const int X_VAL = 0;
    static const int Y_VAL = 1;
    static const int Z_VAL = 2;

    static const int ROLL_VAL = 3;
    static const int PITCH_VAL = 4;
    static const int YAW_VAL = 5;
    //rs : pitch, roll, yaw

    static const int POSE_AZIMUTH = 0;
    static const int POSE_PITCH = 1;
    static const int POSE_ROLL = 2;

    float fingerFactor;

    //Trackball
    mat4 tEye;
    mat4 projectionEye;

    vec4 rEye;
    vec4 cur_eye;
    bool tb_start;
    bool motion;
    int cur_x,cur_y;
    int diff_x,diff_y;

    double *dof_acc_val;

    /*
     * [0] : Azimuth
     * [1] : Pitch
     * [2] : Roll
     */
    float poseFactor[3];
    float startPose[3];
    // Update rate
    int		g_graphicRenderingCounter;
    double	g_updateRateGraphicElapsedTime;
    double	g_averageUpdateRateGraphicLoop;
    double	g_FPS;
    double	g_updateRateGraphicLoop, g_prevTimeGraphicLoop;


    int nowControl;

    // Window size
    GLuint	g_width;
    GLuint	g_height;

    //obj_animation
    bool obj_animation;
    int objCnt;
    int objAdder;


    float distort_offset;
    vec4 spot_light_position;
    vec4 spot_light_lookat;
    vec4 directional_light_dir;

    BYTE* pByte;

    bool flat_shading;
    bool light_animation;
    // Select the shading mode
    GLuint shading ;

    //light toggles
    bool direction_toggle;
    bool point_toggle;
    bool spot_toggle;

    // Global parameters
    GLfloat	g_theta;
    int		g_magFlag;

    // Shader ID
    GLuint	g_IDShader;
    GLuint	g_vertexShaderID;
    GLuint	g_fragmentShaderID;
    GLuint g_RenderingVShaderID;
    GLuint g_RenderingFShaderID;
    GLuint g_RenderingVPositionID;
    GLuint g_RenderingVNormalID;
    GLuint g_RenderingProjectionMatID;
    GLuint g_RenderingModelViewMatID;

    GLuint g_RenderingAmbientID;
    GLuint g_RenderingDiffuseID;
    GLuint g_RenderingSpecularID;
    GLuint g_RenderingLightPosID;




    // Buffer ID
    GLuint	g_VAID;
    GLuint	*g_VBIDvertices;
    GLuint	*g_VBIDnormals;
    GLuint	*g_IBIDelements;

    GLuint	g_VBIDbackground;
    GLuint	g_VBIDbackground_normals;

    std::vector<vec4> background_vertices;
    std::vector<vec3> background_normals;


    bool	g_bWireFrame;



    float rs[3];
    float ts[3];
    float ss[3];
    float default_rs[3];
    float default_ts[3];
    float default_ss[3];
	

    struct key_value{
        float rotate[3];
        float scale[3];
        float translate[3];
    };
    std::vector<key_value> kv;
    std::vector<int> key_frame;
    int frame_cnt;
    bool keyFrame_animation;
    mat4 iKey;



    Obj3D g_BVMesh;
    GLuint g_BVMeshVertexBufferID;
    GLuint g_BVMeshElementBufferID;

    float rot;


    double xLen;
    double yLen;
    double zLen;


    int numOfObstacles1;
    Obj3D* obstacles1;

    bool clipping;

    int NUM_OBJECTS;
    bool *g_IntersectionFlag;

    std::vector<Obj3D*> g_ObjectList;

    //about game playing
    int gameState;
	bool cameraFollow;

	static const int GAME_START = 0;
	static const int GAME_FLYING =1;
	static const int GAME_FLYING_STABLE =2;

public:

    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);
	
	void setCameraFollow(bool );
	void setControllerMode(bool );

    //about game playing
    bool checkStartPose();
    double calcStartSpeed();
    double calcStartAngle();

    void setPose();
    void changeCurrentEye(int what, double val);


    void setf4(const char * uniform_name, float x, float y, float z,float w);

    void setf3(const char * uniform_name, float x, float y, float z);
    void setf1(const char * uniform_name, float x);

    void setVAVBObject();

    // Setting object's modelMatrix
    void setModel( void );

    // Setting light's modelMatrix
    void setLight( void );


    void setView( void );

    // Setting object's projectionMatrix
    void setProjection( void );
    ////////////////////////////////////////////////////////////////////////////////////////////////////////

	void command(int);
    void restoreModel();
    void restoreView();
    void restore();
    void clearMesh();


    void initAirplaneM();
    void setObjectM(mat4 modifiedM);

    void static_matrix(float rot[3],float trans[3],float scale[3],int idx);
    void addKeyFrame(float rot[3],float trans[3],float scale[3],int frame);
    void keyFrameAnimate(int frame);
    void animate(int idx,int cnt);
    void init( void );
    void readOBJs();
    void drawBackground();
    void drawOBJ(Obj3D*);
    void drawOBJs();


    void obstacles1Maker(int);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////

    void destroyShaders();

    void destroyVBO();

    void cleanup();


    void idle(int tick);


    void keyboardDirection (int key, int x, int y);

    void keySelect( unsigned char key, int x, int y );

    //////Trackball/////////
    void trackball(void);

    void reshape( int width, int height );

    void setValue(int what, double val);
    void setFingerFactor(float val);
    void setPoseFactor(int what, float val);

    void mouseMoveEvent(QMouseEvent *);
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void keyPressEvent(QKeyEvent *e);

    void setNowControl(int);

    void drawBoundingBox();
    bool testIntersection();

    void setBoundaryVisible(bool is);

	
    void flyingStartAnimate(int frame);
};

#endif // GLWIDGET_H
